use crate::xueliuhz::constant::MJFanXing::*;
use crate::xueliuhz::*;
// use lazy_static::lazy_static;
use itertools::Itertools;
use log::info;
use mahjong_lib::TileType::*;
use mahjong_lib::*;
use std::collections::HashSet;
use tge::algorithm::{catvv, findv, remove_nv};

// 手牌是否可以点炮胡或者自摸胡
pub fn has_hu(tiles: &Vec<u8>, tile: u8) -> bool {
    let mut ts = tiles.clone();
    // 中间运算用到的Tiles实例
    let mut ti_hu1 = MJTiles::new();
    let mut ti_hu2 = MJTiles::new();
    let mut tss: HashSet<u8> = HashSet::from_iter(ts.iter().cloned());
    // 手牌只有红中的情况...
    if tss.len() == 1 && ts[0] == 35 {
        return tile == 35 || tile == 0;
    }
    // 手上已有4张，外面没有了...
    let num = ts.iter().filter(|&n| *n == tile).count();
    if num == 4 && tile != 35 {
        return false;
    }
    if tile != 0 {
        ts.push(tile);
    }
    let lz: Vec<u8> = vec![35];
    ti_hu1.assign(&ts, &lz);
    // 七对（红中不能单吊任意牌)
    if ts.len() == 14 {
        let mut no_pair_len = 0;
        for i in 0..ti_hu1[NOZI].bucket_len {
            if ti_hu1[NOZI].bucket[i as usize] % 2 == 1 {
                no_pair_len += 1;
            }
        }
        if no_pair_len <= ti_hu1[JIAN].n {
            if tile > 0 && ti_hu1[NOZI].bucket[tile as usize - 1] > 1
                || ti_hu1.laizi.contains(&tile)
            {
                return true;
            }
        }
    }
    if ti_hu1.is_hu() {
        if ti_hu1[JIAN].n == 0 || num > 0 {
            return true;
        }
        if tile != 0 {
            tss.insert(tile);
        }
        //防止红中单吊没有关系的牌...
        for t in &tss {
            let tcount = if *t < 30 {
                ti_hu1[NOZI].bucket[*t as usize - 1]
            } else {
                ti_hu1[ZI].bucket[*t as usize - 30 - 1]
            };
            if *t == tile && tcount <= 1 {
                continue;
            }
            let mut tmpv = ts.clone();
            if tcount > 1 {
                remove_nv(&mut tmpv, 2, *t);
            } else {
                remove_nv(&mut tmpv, 1, *t);
                remove_nv(&mut tmpv, 1, 35);
            }
            tmpv.push(31);
            tmpv.push(31);
            ti_hu2.assign(&tmpv, &lz);
            if ti_hu2.is_hu() {
                return true;
            }
        }
    }
    false
}

// 补上n张牌后判断是否胡
pub fn has_hu_bu(tiles: &Vec<u8>, bu_count: u8, bu_tile: u8, tile: u8) -> bool {
    let mut ts = tiles.clone();
    for n in 0..bu_count as usize {
        ts.push(bu_tile);
    }
    has_hu(&ts, tile)
}

// 多个函数中用到，抽成一个函数...
pub fn hand_nt(hand: &mut Vec<u8>, nowtile: &mut u8, ke: u8) -> u64 {
    if hand.contains(&ke) {
        remove_nv(hand, 1, ke);
    } else if ke == *nowtile {
        *nowtile = 0;
    } else if hand.contains(&35) {
        remove_nv(hand, 1, 35);
    } else if *nowtile == 35 {
        *nowtile = 0;
    } else {
        return 0;
    }
    1
}

// 血流红中玩法不会出现5张的牌，兼容其他玩法
pub fn fx_fan_gen_count(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_all;
    ti[ALL].tcount[4] as u64 + ti[ALL].tcount[5] as u64
}

pub fn fx_qi_dui(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand_now;
    if ti.tiles_len != 14 {
        return 0;
    };
    let lzcount = ti.laizi_count;
    let needlz = ti[NOZI].tcount[1] + ti[NOZI].tcount[3];
    if needlz > lzcount {
        return 0;
    };
    let ret = ti[NOZI].tcount[4] + ti[NOZI].tcount[3] + (lzcount - needlz) / 2;
    if ret == 0 {
        1
    } else {
        (ret * 10) as u64
    }
}

pub fn fx_yi_tiao_long(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand_now;
    let mut lzcount: u8;
    let yitiaolong: Vec<Vec<u8>> = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
    let mut tmp_ytl: Vec<Vec<u8>> = vec![];
    let mut hands: Vec<u8> = vec![];
    let mut cphands: Vec<u8> = vec![];
    let mut cpos: Vec<u8> = vec![];

    for color in WAN as usize..TONG as usize + 1 {
        hands.clear();
        ti.get_hands_nozi(&mut hands, 0);
        ti.get_hands_nozi(&mut cphands, 0);
        lzcount = ti.laizi_count;
        tmp_ytl = yitiaolong.clone();
        for tile in &cphands {
            if tile / 10 != color as u8 {
                continue;
            }
            for mut oneshun in &mut tmp_ytl {
                cpos = oneshun.clone();
                for t in cpos {
                    if t == tile % 10 {
                        remove_nv::<u8>(&mut oneshun, 1, t);
                        remove_nv::<u8>(&mut hands, 1, *tile);
                    }
                }
            }
        }
        let mut remain = 0u8;
        for oneshun in &tmp_ytl {
            remain += oneshun.len() as u8;
        }
        if lzcount < remain {
            continue;
        }
        return if has_hu_bu(&hands, lzcount - remain, 35, 0) {
            1
        } else {
            0
        };
    }
    0
}

//门清返回1，否则返回0
pub fn fx_men_qing(csx: &XlhzTiles) -> u64 {
    for i in 0..csx.cpg.len() {
        match &csx.cpg[i].cpg_type {
            CPGType::GANG => {
                if csx.cpg[i].gang_type == GangType::AN {
                    continue;
                } else {
                    return 0;
                }
            }
            _ => {
                return 0;
            }
        }
    }
    1
}

//全求人返回1，否则返回0
//红中血流没有这个番型...
pub fn fx_quan_qiu_ren(csx: &XlhzTiles) -> u64 {
    if csx.cpg.len() != 4 {
        return 0;
    }
    for i in 0..csx.cpg.len() {
        match &csx.cpg[i].cpg_type {
            CPGType::GANG => {
                if csx.cpg[i].gang_type == GangType::AN {
                    return 0;
                }
            }
            _ => {}
        }
    }
    1
}

//断幺九返回1，否则返回0
pub fn fx_duan_yao_jiu(csx: &XlhzTiles) -> u64 {
    let bkt = &csx.ti_all[NOZI].bucket;
    let cnt = bkt[0] + bkt[8] + bkt[10] + bkt[18] + bkt[20] + bkt[28];
    if cnt != 0 {
        0
    } else {
        1
    }
}

//18罗汉返回1，否则返回0
pub fn fx_18_luo_han(csx: &XlhzTiles) -> u64 {
    if csx.ti_all.tiles_len == 18 {
        1
    } else {
        0
    }
}

//对对胡返回1，否则返回0
pub fn fx_dui_dui_hu(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand_now;
    let needlz = ti[NOZI].tcount[1] * 2 + ti[NOZI].tcount[2] + ti[NOZI].tcount[4] * 2;
    if needlz - 1 > ti.laizi_count {
        return 0;
    }
    1
}

//碰碰胡
pub fn fx_peng_peng_hu(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand;
    let nt = csx.now_tile as u8;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands(&mut hands, 0);

    if nt != 35 && !hands.contains(&nt) {
        return 0;
    }
    fx_dui_dui_hu(csx)
}

pub fn fx_jue_zhang(csx: &XlhzTiles) -> u64 {
    0
}

//金钩吊返回1，否则返回0
pub fn fx_jin_gou_diao(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand_now;
    if ti.tiles_len == 1 {
        1
    } else {
        0
    }
}

//清一色返回1，否则返回0
pub fn fx_qing_yi_se(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_all;
    let mut colors: [u8; 3] = [0, 0, 0];
    for i in WAN as usize..TONG as usize + 1 {
        if ti.counters[i].n > 0 {
            colors[i] = 1;
        }
    }
    if (colors[WAN as usize] + colors[TIAO as usize] + colors[TONG as usize]) == 1 {
        1
    } else {
        0
    }
}

//258返回1，否则返回0
pub fn fx_258(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_all;
    let mut total = 0u8;
    let no258: [usize; 6] = [0, 2, 3, 5, 6, 8];
    for i in WAN as usize..TONG as usize + 1 {
        for j in 0..6 {
            total += ti.counters[i].bucket[no258[j]];
        }
    }
    if total == 0 {
        1
    } else {
        0
    }
}

pub fn fx_jiang_dui(csx: &XlhzTiles) -> u64 {
    if fx_dui_dui_hu(csx) == 1 && fx_258(csx) == 1 {
        return 1;
    }
    0
}

pub fn fx_kan(csx: &XlhzTiles) -> u64 {
    let hutile = csx.now_tile;
    if hutile == 0 || hutile % 10 == 1 || hutile % 10 == 9 || (hutile >= 30 && hutile != 35) {
        return 0;
    }

    let ti = &csx.ti_hand_now;

    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);

    if !ti.is_lai_zi(hutile as u8) {
        let hcp = hands.contains(&(hutile as u8 + 1));
        let hcs = hands.contains(&(hutile as u8 - 1));
        if hcp || hcs {
            let mut cphand = hands.clone();
            let mut lzcount = ti.laizi_count;
            remove_nv(&mut cphand, 1, hutile as u8);
            if hcs {
                remove_nv(&mut cphand, 1, (hutile - 1) as u8);
            } else {
                if lzcount > 0 {
                    lzcount -= 1;
                } else {
                    return 0;
                }
            }
            if hcp {
                remove_nv(&mut cphand, 1, (hutile + 1) as u8);
            } else {
                if lzcount > 0 {
                    lzcount -= 1;
                } else {
                    return 0;
                }
            }
            if has_hu_bu(&cphand, lzcount, 35, 0) {
                return 1;
            }
        }
    } else {
        for i in 0..hands.len() {
            let ht = hands[i];
            if ht % 10 > 7 {
                continue;
            }
            let mut cphand = hands.clone();
            let mut lzcount = ti.laizi_count;
            remove_nv(&mut cphand, 1, ht);
            if cphand.contains(&(ht + 2)) {
                remove_nv(&mut cphand, 1, ht + 2);
            } else {
                if lzcount > 0 {
                    lzcount -= 1;
                } else {
                    continue;
                }
            }
            if lzcount > 0 {
                lzcount -= 1;
            } else {
                continue;
            }
            if has_hu_bu(&cphand, lzcount, 35, 0) {
                return 1;
            }
        }
    }
    0
}

pub fn fx_zhuo_wu_kui(csx: &XlhzTiles) -> u64 {
    if csx.now_tile != 5 && csx.now_tile != 35 {
        return 0;
    }
    //修复bug，判断kan时，不破坏m
    let mut cpm = XlhzTiles::new();
    let mut ts: Vec<u8> = vec![];
    csx.ti_hand.get_hands(&mut ts, 0);
    cpm.assign(&ts, 5, csx.que, &csx.cpg, csx.hutype);
    fx_kan(&mut cpm)
}

//12,13,14,16,18
pub fn fx_lv_yi_se(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_all;
    let bkt = &ti[NOZI].bucket;
    let nolv: Vec<u8> = vec![
        0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 14, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
    ];
    let mut total = 0u8;
    for i in 0..nolv.len() {
        total += bkt[nolv[i] as usize];
    }
    if total != 0 {
        return 0;
    }
    let ti = &csx.ti_hand_now;
    let mut lzcount = ti.laizi_count;
    if lzcount != 0 {
        let liutiao = ti[NOZI].bucket[16 - 1];
        if liutiao == 0 {
            return 1;
        }
        let mut hands: Vec<u8> = vec![];
        //非字牌去掉6条，放到hands里
        ti.get_hands_nozi(&mut hands, 16);
        let mod_liu = if liutiao > 3 { liutiao % 3 } else { liutiao };
        let mut fj: u8 = 0;
        //消耗癞子
        for j in 0..3 - mod_liu {
            fj = j;
            if lzcount > 0 {
                lzcount -= 1;
            } else {
                break;
            }
        }
        //如果没有走break
        if fj == 3 - mod_liu {
            if has_hu_bu(&hands, lzcount, 35, 0) {
                return 1;
            }
        }
        //恢复癞子个数
        lzcount = ti.laizi_count;
        if mod_liu <= 2 {
            //消耗癞子
            for j in 0..2 - mod_liu {
                fj = j;
                if lzcount > 0 {
                    lzcount -= 1;
                } else {
                    break;
                }
            }
            //如果没有走break
            if fj == 2 - mod_liu {
                if has_hu_bu(&hands, 2, 1, 0) {
                    return 1;
                }
            }
        }
        return 0;
    }
    return 1;
}

pub fn fx_jiu_lian_bao_deng(csx: &XlhzTiles) -> u64 {
    if fx_qing_yi_se(csx) == 0 {
        return 0;
    }

    let ti = &csx.ti_hand_now;

    let cnz = &ti[NOZI];
    let mut new_hand: Vec<u8> = vec![];
    for i in 0..cnz.bucket_len {
        let tcnt = cnz.bucket[i as usize];
        if tcnt > 0 {
            for j in 0..tcnt {
                new_hand.push((i + 1) % 10);
            }
        }
    }
    let mut lzcount = ti.laizi_count;

    let bao_deng: Vec<u8> = vec![1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9];
    for i in 0..13 {
        let t = bao_deng[i];
        if !new_hand.contains(&t) {
            if lzcount == 0 {
                return 0;
            }
            lzcount -= 1;
            continue;
        }
        remove_nv(&mut new_hand, 1, t);
    }
    1
}

pub fn fx_lian_qi_dui(csx: &XlhzTiles) -> u64 {
    if fx_qi_dui(csx) == 0 || fx_qing_yi_se(csx) == 0 {
        return 0;
    }

    let ti = &csx.ti_hand_now;

    let cnz = &ti[NOZI];
    let mut lzcount = ti.laizi_count;

    let mut f = 0u8;
    for i in 0..cnz.bucket_len {
        let tcnt = cnz.bucket[i as usize];
        if tcnt > 0 {
            f = i + 1;
            break;
        }
    }
    let mut lqd: Vec<u8> = vec![];
    for i in 0..7 {
        lqd.push(f + i);
        lqd.push(f + i);
    }
    for i in 0..ti.tiles_len {
        let t = ti.tiles[i as usize];
        if t == 35 {
            continue;
        }
        if !lqd.contains(&t) {
            return 0;
        }
        remove_nv(&mut lqd, 1, t);
    }
    if lqd.len() != lzcount as usize {
        return 0;
    }
    1
}

pub fn fx_dai_yao_jiu(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand_now;

    let c = &csx.cpg;
    let yaojiu: HashSet<u8> = [1, 11, 21, 9, 19, 29, 35].into_iter().collect();

    for i in 0..c.len() {
        if c[i].cpg_type == CPGType::GANG || c[i].cpg_type == CPGType::PENG {
            if !yaojiu.contains(&c[i].tile) {
                return 0;
            }
        }
    }

    let mut lzcount = ti.laizi_count;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);

    for &tile in &hands {
        let dian = tile % 10;
        if dian > 3 && dian < 7 {
            return 0;
        }
    }

    let yj = vec![1u8, 11, 21, 9, 19, 29];
    for i in 0..6 {
        let one = yj[i];
        let two = if one % 10 == 1 { one + 1 } else { one - 1 };
        let thr = if one % 10 == 1 { one + 2 } else { one - 2 };
        while hands.contains(&one) && hands.contains(&two) && hands.contains(&thr) {
            remove_nv(&mut hands, 1, one);
            remove_nv(&mut hands, 1, two);
            remove_nv(&mut hands, 1, thr);
        }
    }

    let mut no_yaojiu = vec![];
    for i in 0..hands.len() {
        if yaojiu.contains(&hands[i]) {
            continue;
        }
        no_yaojiu.push(hands[i]);
    }

    while no_yaojiu.len() != 0 {
        let tile = no_yaojiu.pop().unwrap();
        let start = if tile % 10 < 4 {
            tile / 10 * 10 + 1
        } else {
            tile / 10 * 10 + 7
        };
        for i in 0..3 {
            let tmp = start + i;
            if hands.contains(&tmp) {
                remove_nv(&mut hands, 1, tmp);
                if no_yaojiu.contains(&tmp) && tmp != tile {
                    remove_nv(&mut no_yaojiu, 1, tmp);
                }
            } else {
                if lzcount > 0 {
                    lzcount -= 1;
                } else {
                    return 0;
                }
            }
        }
    }

    if has_hu_bu(&hands, lzcount, 35, 0) {
        1
    } else {
        0
    }
}

pub fn fx_quan_yao_jiu(csx: &XlhzTiles) -> u64 {
    let ti = &csx.ti_hand_now;

    let c = &csx.cpg;
    let yaojiu: HashSet<u8> = [1, 11, 21, 9, 19, 29, 35].into_iter().collect();

    for i in 0..c.len() {
        if c[i].cpg_type == CPGType::GANG || c[i].cpg_type == CPGType::PENG {
            if !yaojiu.contains(&c[i].tile) {
                return 0;
            }
        }
    }

    let mut lzcount = ti.laizi_count;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);

    for &tile in &hands {
        let dian = tile % 10;
        if dian > 3 && dian < 7 {
            return 0;
        }
    }
    let yj: HashSet<u8> = [1, 11, 21, 9, 19, 29].into_iter().collect();
    for i in 0..hands.len() {
        if yj.contains(&hands[i]) {
            continue;
        }
        return 0;
    }
    let mut needlz = ti[NOZI].tcount[1] + ti[NOZI].tcount[3];
    if needlz <= lzcount {
        return 1;
    } else {
        needlz = ti[NOZI].tcount[1] * 2 + ti[NOZI].tcount[2] + ti[NOZI].tcount[4] * 2;
        if needlz <= lzcount + 1 {
            return 1;
        }
    }
    0
}

fn hand_list_com(hands: &Vec<u8>) -> Vec<Vec<u8>> {
    let mut res: Vec<Vec<u8>> = Vec::new();
    let shand: Vec<u8> = hands
        .iter()
        .cloned()
        .collect::<std::collections::HashSet<_>>()
        .into_iter()
        .collect();

    for i in 0..shand.len() {
        if i + 1 == shand.len() {
            continue;
        }
        for m in shand.iter().combinations(i + 1) {
            let _com: Vec<u8> = m.into_iter().cloned().collect();
            res.push(_com);
        }
    }

    res
}

fn get_all_ke_list(ti: &MJTiles, nowtile: u8, kes: u8, ankes: &Vec<u8>) -> Vec<Vec<u8>> {
    let mut res: Vec<Vec<u8>> = vec![];
    let mut new_hand: Vec<u8> = vec![];

    for i in 0..ti[NOZI].bucket_len {
        if ti[NOZI].bucket[i as usize] > 0 {
            new_hand.push(i + 1);
        }
    }

    let mut hand: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hand, 0);

    for m in new_hand.iter().combinations(kes as usize - ankes.len()) {
        let mut _com: Vec<u8> = m.into_iter().cloned().collect();

        let mut cpkes = ankes.clone();
        let mut cphand = hand.clone();
        let mut lzcount = ti.laizi_count;

        for &t in &_com {
            let count = ti[NOZI].bucket[(t - 1) as usize];
            let rcount = if count > 3 { 3 } else { count };
            if lzcount < 3 - rcount {
                break;
            }
            remove_nv(&mut cphand, rcount as usize, t);
            lzcount -= 3 - rcount;
            cpkes.push(t as u8);
        }

        if cpkes.len() != kes as usize {
            continue;
        }
        if !has_hu_bu(&cphand, lzcount, 35, nowtile) {
            continue;
        }
        if nowtile == 35 {
            lzcount += 1;
        } else if nowtile > 0 {
            cphand.push(nowtile);
        }
        let mut is_not_append = true;

        let hlc = hand_list_com(&cphand);
        for rcom in hlc {
            let mut cp2hand = cphand.clone();
            let mut cp2kes = cpkes.clone();
            let mut lzcount2 = lzcount;
            let mut add_rcom = true;

            for &r in &rcom {
                let num = cp2hand.iter().filter(|&&n| n == r).count();
                let rcount = if num > 3 { 3 } else { num as u8 };
                if lzcount2 < 3 - rcount {
                    add_rcom = false;
                    continue;
                }
                remove_nv(&mut cp2hand, rcount as usize, r);
                lzcount2 -= 3 - rcount;
            }
            if add_rcom {
                if !has_hu_bu(&cp2hand, lzcount2, 35, 0) {
                    continue;
                }
                catvv::<u8>(&mut cp2kes, &rcom);
            }
            is_not_append = false;
            res.push(cp2kes);
        }
        if is_not_append {
            res.push(cpkes);
        }
    }

    res
}

pub fn has_an_ke(cards: &XlhzTiles, kes: u8) -> u64 {
    let mut ret = MJRet { f: 0 };
    let mut now_tile = cards.now_tile;
    let mut handnow = false;
    if cards.hutype == HuType::ZIMO {
        handnow = true;
        now_tile = 0;
    }
    let mut ankes: Vec<u8> = Vec::new();
    let mut elsekes: Vec<u8> = Vec::new();
    let mut allkes: Vec<Vec<u8>>;
    for cpg in &cards.cpg {
        if cpg.cpg_type == CPGType::GANG && cpg.gang_type == GangType::AN {
            ankes.push(cpg.tile);
        } else if cpg.cpg_type != CPGType::CHI {
            elsekes.push(cpg.tile);
        }
    }
    if kes > ankes.len() as u8 {
        allkes = get_all_ke_list(
            if handnow {
                &cards.ti_hand_now
            } else {
                &cards.ti_hand
            },
            now_tile,
            kes,
            &ankes,
        );
    } else if kes == ankes.len() as u8 {
        allkes = vec![ankes];
    } else {
        return 0; // No AnKe found, return 0
    }
    if allkes.is_empty() {
        return 0; // No combinations found, return 0
    }
    if allkes.len() == 1 {
        return ret.v2ret(&allkes[0], kes); // Assume a single combination is valid
    }

    let mut silian: Vec<Vec<u8>> = Vec::new();
    let mut sanlian: Vec<Vec<u8>> = Vec::new();
    let mut tongke: Vec<Vec<u8>> = Vec::new();
    for kets in &allkes {
        let mut kelist = kets.clone();
        catvv::<u8>(&mut kelist, &elsekes);
        // Sort `kelist` to prepare for comparisons.
        kelist.sort_unstable();
        if kes == 4 && kelist[kelist.len() - 1] - kelist[0] == kes - 1 {
            // Direct return if it's a "silian" (sequential "ke"s).
            return ret.v2ret(&kelist, kes);
        }
        match kelist.len() {
            4 => {
                if kelist[3] - kelist[0] == 3 {
                    silian.push(kelist.clone());
                }
                if kelist[2] - kelist[0] == 2 || kelist[3] - kelist[1] == 2 {
                    sanlian.push(kelist.clone());
                }
            }
            3 => {
                if kelist[2] - kelist[0] == 2 {
                    sanlian.push(kelist.clone());
                }
            }
            _ => {}
        }
        let _tmps: Vec<u8> = kelist.iter().map(|&kk| kk % 10).collect();
        let _tmpset: std::collections::HashSet<u8> = _tmps.iter().cloned().collect();
        if _tmpset.len() < kelist.len() {
            tongke.push(kelist);
        }
    }

    if !silian.is_empty() {
        return ret.v2ret(&silian[0], kes);
    }

    if !sanlian.is_empty() {
        let tc = if handnow {
            &cards.ti_hand_now
        } else {
            &cards.ti_hand
        };
        let (best_idx, _) = sanlian
            .iter()
            .enumerate()
            .map(|(i, kets)| {
                let total_card: i32 = kets
                    .iter()
                    .map(|&j| tc[NOZI].bucket[(j - 1) as usize] as i32)
                    .sum();
                (i, total_card)
            })
            .max_by_key(|&(_, total_card)| total_card)
            .unwrap_or((0, 0));

        return ret.v2ret(&sanlian[best_idx], kes);
    }

    if !tongke.is_empty() {
        return ret.v2ret(&tongke[0], kes);
    }

    ret.v2ret(&allkes[0], kes)
}

pub fn fx_yi_se_shuang_long_hui(cards: &XlhzTiles) -> u64 {
    if fx_qing_yi_se(cards) == 0 {
        return 0;
    }

    let ti = &cards.ti_hand_now;
    let cnz = &ti[NOZI];
    let mut new_hand: Vec<u8> = Vec::new();
    for i in 0..cnz.bucket_len as usize {
        let tcnt = cnz.bucket[i];
        if tcnt > 0 {
            new_hand.extend(vec![((i as u8) + 1) % 10; tcnt as usize]);
        }
    }
    let mut lzcount = ti.laizi_count;

    let mut shuang_long = vec![1, 1, 2, 2, 3, 3, 5, 5, 7, 7, 8, 8, 9, 9];
    for &t in &new_hand {
        match shuang_long.iter().position(|&x| x == t) {
            Some(index) => {
                shuang_long.remove(index);
            }
            None => {
                return 0;
            }
        }
    }

    if shuang_long.len() != lzcount as usize {
        return 0;
    }

    1
}

pub fn fx_quan_shuang_ke(cards: &XlhzTiles) -> u64 {
    let mut hands: Vec<u8> = vec![];
    if fx_dui_dui_hu(cards) == 0 {
        return 0;
    }

    let ti = &cards.ti_all;
    ti.get_hands_nozi(&mut hands, 0); // Assuming this method is available and correctly implemented.

    for &t in &hands {
        if t >= 30 || t % 2 != 0 {
            return 0;
        }
    }

    1
}

pub fn fx_quan_dai_wu(cards: &XlhzTiles) -> u64 {
    if fx_quan_shuang_ke(cards) == 0 {
        return 0;
    }

    // Check CPG for 5-tiles.
    for cpg in &cards.cpg {
        let pat = cpg.com;
        if !pat.contains(&5) && !pat.contains(&15) && !pat.contains(&25) {
            return 0;
        }
    }

    let ti = &cards.ti_hand_now;
    let mut lzcount = ti.laizi_count;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0); // Assuming this method is available and correctly implemented.

    // Check for terminal tiles in the hand; they should not exist.
    for &t in &hands {
        let digit = t % 10;
        if digit < 3 || digit > 7 {
            return 0;
        }
    }

    // Check for the presence of 5-tiles in the hand and adjust the hand accordingly.
    let fives = [5, 15, 25];
    for &five in &fives {
        if hands.contains(&five) {
            hands.retain(|&x| x != five); // Remove 5-tiles from the hand.
        }
    }

    // Check if there are any non-5-tiles left in the hand.
    let mut not_five: Vec<u8> = hands
        .iter()
        .filter(|&&t| !fives.contains(&t))
        .cloned()
        .collect();

    // Adjust the remaining hand for the non-5-tiles, considering the laizi tiles.
    while let Some(&tile) = not_five.last() {
        not_five.pop(); // Remove the last element from not_five.
        let start = if tile % 10 < 5 {
            tile / 10 * 10 + 1
        } else {
            tile / 10 * 10 + 7
        };

        for i in 0..3 {
            let target_tile = start + i;
            if hands.contains(&target_tile) {
                hands.retain(|&x| x != target_tile); // Remove the target tile from the hand.
            } else {
                if lzcount > 0 {
                    lzcount -= 1; // Use a laizi tile if possible.
                } else {
                    return 0; // Not enough laizi tiles to complete the sequence.
                }
            }
        }
    }

    // Check if the hand is winning using the remaining laizi tiles.
    if has_hu_bu(&hands, lzcount, 35, 0) {
        1
    } else {
        0
    }
}

pub fn fx_da_yu_wu(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_all;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);

    if hands.iter().any(|&t| t < 30 && t % 10 <= 5) {
        0
    } else {
        1
    }
}

pub fn fx_xiao_yu_wu(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_all;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);

    if hands.iter().any(|&t| t < 30 && t % 10 >= 5) {
        0
    } else {
        1
    }
}

pub fn fx_bian(cards: &XlhzTiles) -> u64 {
    let hutile = cards.now_tile;
    if hutile == 0 || (hutile > 30 && hutile != 35) {
        return 0;
    }

    let ti = &cards.ti_hand_now;
    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);
    let mut lzcount = ti.laizi_count;

    match hutile % 10 {
        7 if hutile != 35 => {
            if !findv(&hands, &(hutile + 2)) {
                return 0;
            }
            remove_nv(&mut hands, 1, hutile);
            remove_nv(&mut hands, 1, hutile + 2);
            if findv(&hands, &(hutile + 1)) {
                remove_nv(&mut hands, 1, hutile + 1);
            } else if lzcount == 0 {
                return 0;
            } else {
                lzcount -= 1;
            }
            if has_hu_bu(&hands, lzcount, 35, 0) {
                1
            } else {
                0
            }
        }
        3 if hutile != 35 => {
            if !findv(&hands, &(hutile - 2)) {
                return 0;
            }
            remove_nv(&mut hands, 1, hutile);
            remove_nv(&mut hands, 1, hutile - 2);
            if findv(&hands, &(hutile - 1)) {
                remove_nv(&mut hands, 1, hutile - 1);
            } else if lzcount == 0 {
                return 0;
            } else {
                lzcount -= 1;
            }
            if has_hu_bu(&hands, lzcount, 35, 0) {
                1
            } else {
                0
            }
        }
        _ => {
            if hutile == 35 {
                let aa = [[1, 2], [8, 9], [11, 12], [18, 19], [21, 22], [28, 29]];
                for &[arr0, arr1] in &aa {
                    if !findv(&hands, &arr0) || !findv(&hands, &arr1) {
                        continue;
                    }
                    let mut copyhands = hands.clone();
                    let mut copylz = lzcount;
                    remove_nv(&mut copyhands, 1, arr0);
                    remove_nv(&mut copyhands, 1, arr1);
                    copylz -= 1;
                    if has_hu_bu(&copyhands, copylz, 35, 0) {
                        return 1;
                    }
                }
            }
            0
        }
    }
}

pub fn fx_dan_diao(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_hand;

    let hutile = cards.now_tile;
    let mut hands: Vec<u8> = vec![];
    if !ti.is_lai_zi(hutile) {
        if ti[NOZI].bucket[(hutile - 1) as usize] == 0 {
            return 0;
        }
        ti.get_hands(&mut hands, 0);
        remove_nv(&mut hands, 1, hutile);
        if has_hu_bu(&hands, 2, 31, 0) {
            1
        } else {
            0
        }
    } else {
        ti.get_hands(&mut hands, 0);
        let tss: std::collections::HashSet<u8> = hands.iter().cloned().collect();
        for &t in &tss {
            let mut cphand = hands.clone();
            remove_nv(&mut cphand, 1, t);
            if has_hu_bu(&cphand, 2, 31, 0) {
                return 1;
            }
        }
        0
    }
}

pub fn fx_lao_shao_pei(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_hand_now;

    let shun_tiles: Vec<Vec<u8>> = vec![
        vec![1, 2, 3, 7, 8, 9],
        vec![11, 12, 13, 17, 18, 19],
        vec![21, 22, 23, 27, 28, 29],
    ];

    let mut hands: Vec<u8> = vec![];
    ti.get_hands_nozi(&mut hands, 0);

    for shun in shun_tiles {
        let mut cphand = hands.clone();
        let mut lzcount = ti.laizi_count;
        let mut has_shun = true;
        let mut le_three_c = 0;
        let mut ge_seven_c = 0;

        for &tile in &shun {
            if !findv(&cphand, &tile) {
                if lzcount == 0 {
                    has_shun = false;
                    break;
                }
                lzcount -= 1;
                continue;
            }
            if tile % 10 <= 3 {
                le_three_c += 1;
            }
            if tile % 10 >= 7 {
                ge_seven_c += 1;
            }
            remove_nv(&mut cphand, 1, tile);
        }

        if !has_shun || le_three_c == 0 || ge_seven_c == 0 {
            continue;
        }

        let mut nt = cards.now_tile;
        if findv(&cphand, &nt) {
            remove_nv(&mut cphand, 1, nt);
        } else {
            nt = 0;
        }

        if has_hu_bu(&cphand, lzcount, 35, nt) {
            if shun.len() == 1 {
                return 0;
            }
            let mut ret = MJRet { f: 0 };
            return ret.v2ret(&shun, shun.len() as u8);
        }
    }
    0
}

pub fn fx_shuang_tong_ke(cards: &XlhzTiles) -> u64 {
    let mut cpgtiles: Vec<u8> = Vec::new();
    for cpg in &cards.cpg {
        cpgtiles.push(cpg.tile);
    }

    let ti = &cards.ti_gang4to3;

    let mut colors: Vec<u8> = Vec::new();
    let mut hands: Vec<u8> = Vec::new();
    ti.get_hands_nozi(&mut hands, 0);
    for &t in &hands {
        if !colors.contains(&(t / 10)) {
            colors.push(t / 10);
        }
    }

    if colors.len() == 1 {
        return 0;
    }

    let mut uselz = 0;
    let lzcount = ti.laizi_count;
    let handset: std::collections::HashSet<u8> = hands.iter().cloned().collect();

    let mut tongkes: Vec<Vec<u8>> = Vec::new();
    let mut haskes: Vec<u8> = Vec::new();

    for &tile in &handset {
        if tile > 30 || haskes.contains(&tile) || tile / 10 == colors[1] {
            continue;
        }

        let tile1 = 10 * colors[1] + tile % 10;
        let mut cphand = hands.clone();
        if ti[NOZI].bucket[(tile1 - 1) as usize] < 1 {
            continue;
        }

        let tmpv = vec![tile, tile1];
        for &t in &tmpv {
            let tile_c = ti[NOZI].bucket[(t - 1) as usize];
            uselz += if tile_c >= 3 { 0 } else { 3 - tile_c };
            remove_nv(
                &mut cphand,
                if tile_c >= 3 { 3 } else { tile_c as usize },
                t,
            );
        }

        if uselz > lzcount {
            uselz = 0;
            continue;
        }

        for &p in &cpgtiles {
            if !cphand.contains(&p) || cphand.iter().filter(|&&x| x == p).count() < 3 {
                continue;
            }
            remove_nv(&mut cphand, 3, p);
        }

        if has_hu_bu(&cphand, lzcount - uselz, 35, 0) {
            haskes.push(tile);
            haskes.push(tile1);
            tongkes.push(tmpv);
        }

        uselz = 0;
    }

    if !tongkes.is_empty() {
        let mut tmpv: Vec<u8> = Vec::new();
        for tks in tongkes {
            tmpv.extend_from_slice(&tks);
        }
        let mut ret = MJRet { f: 0 };
        return ret.v2ret(&tmpv, tmpv.len() as u8);
    }

    0
}

pub fn fx_yi_ban_gao(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_hand_now;

    let mut hands: Vec<u8> = Vec::new();
    ti.get_hands_nozi(&mut hands, 0);
    let mut uselz = 0;
    let lzcount = ti.laizi_count;
    let handset: std::collections::HashSet<u8> = hands.iter().cloned().collect();

    for &tile in &handset {
        if tile > 30 {
            continue;
        }
        let mut cphand = hands.clone();
        let (tile1, tile2) = match tile % 10 {
            8 => (tile + 1, tile - 1),
            9 => (tile - 1, tile - 2),
            _ => (tile + 1, tile + 2),
        };
        let tmpv = vec![tile, tile1, tile2];
        for &t in &tmpv {
            let tile_c = ti[NOZI].bucket[(t - 1) as usize];
            uselz += if tile_c >= 2 { 0 } else { 2 - tile_c };
            remove_nv(
                &mut cphand,
                if tile_c >= 2 { 2 } else { tile_c as usize },
                t,
            );
        }
        if uselz > lzcount {
            uselz = 0;
            continue;
        }
        if has_hu_bu(&cphand, lzcount - uselz, 35, 0) {
            let mut ret = MJRet { f: 0 };
            return ret.v2ret(&[tile, tile1, tile2], 3);
        }
        uselz = 0;
    }

    0
}

pub fn fx_lian_liu(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_hand_now;

    let mut colors: std::collections::HashSet<u8> = std::collections::HashSet::new();
    for i in WAN as u8..TONG as u8 {
        if ti.counters[i as usize].n > 0 {
            colors.insert(i);
        }
    }

    let mut hands: Vec<u8> = Vec::new();
    ti.get_hands_nozi(&mut hands, 0);
    let mut uselz = 0;
    let lzcount = ti.laizi_count;

    for &color in &colors {
        for i in 1..5 {
            let start = color * 10 + i;
            let mut cphand = hands.clone();
            for j in 0..6 {
                let tile = start + j;
                if findv(&cphand, &tile) {
                    remove_nv(&mut cphand, 1, tile);
                } else {
                    uselz += 1;
                }
            }
            if uselz > lzcount {
                uselz = 0;
                continue;
            }
            if has_hu_bu(&cphand, lzcount - uselz, 35, 0) {
                let mut ret = MJRet { f: 0 };
                return ret.v2ret(&[start], 1);
            }
            uselz = 0;
        }
    }

    0
}

pub fn fx_san_jie_gao(cards: &XlhzTiles) -> u64 {
    let mut cpgtiles: Vec<u8> = Vec::new();
    for cpg in &cards.cpg {
        cpgtiles.push(cpg.tile);
    }

    let ti = &cards.ti_gang4to3;

    let mut hands: Vec<u8> = Vec::new();
    ti.get_hands_nozi(&mut hands, 0);
    let mut uselz = 0;
    let lzcount = ti.laizi_count;
    let handset: std::collections::HashSet<u8> = hands.iter().cloned().collect();

    for &tile in &handset {
        if tile > 30 {
            continue;
        }
        let mut cphand = hands.clone();
        let (tile1, tile2) = match tile % 10 {
            8 => (tile + 1, tile - 1),
            9 => (tile - 1, tile - 2),
            _ => (tile + 1, tile + 2),
        };

        if !findv(&hands, &tile1) || !findv(&hands, &tile2) {
            continue;
        }

        let tmpv = vec![tile, tile1, tile2];
        for &t in &tmpv {
            let tile_c = ti[NOZI].bucket[(t - 1) as usize];
            uselz += if tile_c >= 3 { 0 } else { 3 - tile_c };
            remove_nv(
                &mut cphand,
                if tile_c >= 3 { 3 } else { tile_c as usize },
                t,
            );
        }
        if uselz > lzcount {
            uselz = 0;
            continue;
        }
        for &p in &cpgtiles {
            if !cphand.contains(&p) || cphand.iter().filter(|&x| x == &p).count() < 3 {
                continue;
            }
            remove_nv(&mut cphand, 3, p);
        }
        if has_hu_bu(&cphand, lzcount - uselz, 35, 0) {
            let mut ret = MJRet { f: 0 };
            return ret.v2ret(&[tile, tile1, tile2], 3);
        }
        uselz = 0;
    }

    0
}

pub fn fx_si_jie_gao(cards: &XlhzTiles) -> u64 {
    let mut cpgtiles: Vec<u8> = cards.cpg.iter().map(|cpg| cpg.tile).collect();

    let ti = &cards.ti_gang4to3;
    let mut hands: Vec<u8> = Vec::new();
    ti.get_hands_nozi(&mut hands, 0);
    let mut uselz = 0;
    let lzcount = ti.laizi_count;
    let handset: std::collections::HashSet<u8> = hands.iter().cloned().collect();

    for &tile in &handset {
        if tile > 30 {
            continue;
        }

        let mut cphand = hands.clone();
        let (tile1, tile2, tile3) = match tile % 10 {
            7 => (tile + 1, tile - 1, tile + 2),
            8 => (tile + 1, tile - 1, tile - 2),
            9 => (tile - 1, tile - 2, tile - 3),
            _ => (tile + 1, tile + 2, tile + 3),
        };

        if !findv(&hands, &tile1) || !findv(&hands, &tile2) || !findv(&hands, &tile3) {
            continue;
        }

        let tmpv = vec![tile, tile1, tile2, tile3];
        for &t in &tmpv {
            let tile_c = ti[NOZI].bucket[(t - 1) as usize];
            uselz += if tile_c >= 3 { 0 } else { 3 - tile_c };
            remove_nv(
                &mut cphand,
                if tile_c >= 3 { 3 } else { tile_c as usize },
                t,
            );
        }
        if uselz > lzcount {
            uselz = 0;
            continue;
        }

        for &p in &cpgtiles {
            if !cphand.contains(&p) || cphand.iter().filter(|&x| x == &p).count() < 3 {
                continue;
            }
            remove_nv(&mut cphand, 3, p);
        }

        if has_hu_bu(&cphand, lzcount - uselz, 35, 0) {
            let mut ret = MJRet { f: 0 };
            return ret.v2ret(&[tile, tile1, tile2, tile3], 4);
        }
        uselz = 0;
    }

    0
}

pub fn fx_shi_er_jin_chai(cards: &XlhzTiles) -> u64 {
    let gang_count = cards
        .cpg
        .iter()
        .filter(|cpg| cpg.cpg_type == CPGType::GANG)
        .count();
    if gang_count == 3 {
        1
    } else {
        0
    }
}

pub fn fx_bai_wan_dan(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_all;
    let mut hands: Vec<u8> = Vec::new();
    ti.get_hands(&mut hands, 0);
    let total: u8 = hands.iter().filter(|&&t| t <= 10).sum();
    if total >= 100 {
        1
    } else {
        0
    }
}

pub fn fx_dan_diao_hz(cards: &XlhzTiles) -> u64 {
    let ti = &cards.ti_hand;
    if ti.tiles_len == 1 && cards.now_tile == 35 && ti.tiles[0] == 35 {
        1
    } else {
        0
    }
}

pub fn fx_si_an_ke(cards: &XlhzTiles) -> u64 {
    has_an_ke(cards, 4)
}

pub fn fx_san_an_ke(cards: &XlhzTiles) -> u64 {
    has_an_ke(cards, 3)
}

pub fn fx_shuang_an_ke(cards: &XlhzTiles) -> u64 {
    has_an_ke(cards, 2)
}

pub fn rm_wu_kui(cards: &mut XlhzTiles, _ret_data: u64) -> u64 {
    let ti = &mut cards.ti_hand;
    let wub: [u8; 2] = [4, 6];
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0); 

    for &tile in &wub {
        if ti.find_tile(tile) { 
            remove_nv(&mut hand, 1, tile);
        } else {
            remove_nv(&mut hand, 1, 35); 
        }
    }

    cards.assign(&hand, 0, cards.que, &cards.cpg.clone(), cards.hutype); 

    1 
}

pub fn rm_yi_ban_gao(cards: &mut XlhzTiles, ret_data: u64) -> u64 {
    let ti = &mut cards.ti_hand;
    let lz: Vec<u8> = vec![35]; 
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0); 

    let mut retv: Vec<u8> = Vec::new();
    let ret = MJRet { f: ret_data };
    ret.ret2v(&mut retv); 

    let mut nt = cards.now_tile;

    for _ in 0..2 {
        for &t in &retv[0..3] {
            if hand_nt(&mut hand, &mut nt, t) == 0 {
                cards.assign(&hand, nt, cards.que, &cards.cpg.clone(), cards.hutype);
                return 0;
            }
        }
    }

    cards.assign(&hand, nt, cards.que, &cards.cpg.clone(), cards.hutype);
    1
}

pub fn rm_lao_shao(cards: &mut XlhzTiles, ret_data: u64) -> u64 {
    let ti = &mut cards.ti_hand;
    let lz: Vec<u8> = vec![35];  
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0);  

    let mut retv: Vec<u8> = Vec::new();
    let ret = MJRet { f: ret_data };
    ret.ret2v(&mut retv);  

    let mut nt = cards.now_tile;

    for &t in &retv[..6] {
        if hand_nt(&mut hand, &mut nt, t) == 0 {
            cards.assign(&hand, nt, cards.que, &cards.cpg.clone(), cards.hutype);
            return 0;
        }
    }

    cards.assign(&hand, nt, cards.que, &cards.cpg.clone(), cards.hutype);
    1
}

pub fn rm_lian_liu(cards: &mut XlhzTiles, ret_data: u64) -> u64 {
    let ti = &mut cards.ti_hand;
    let lz: Vec<u8> = vec![35];
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0);

    let mut retv: Vec<u8> = Vec::new();
    let ret = MJRet { f: ret_data };
    ret.ret2v(&mut retv);

    let mut nt = cards.now_tile;

    for i in 0..6 {
        let t = retv[0] + i;
        if hand_nt(&mut hand, &mut nt, t) == 0 {
            cards.assign(&hand, nt, cards.que, &cards.cpg.clone(), cards.hutype);
            return 0;
        }
    }

    cards.assign(&hand, nt, cards.que, &cards.cpg.clone(), cards.hutype);
    1
}

pub fn rm_dan_diao(cards: &mut XlhzTiles, _ret_data: u64) -> u64 {
    let ti = &mut cards.ti_hand;
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0);
    hand.push(cards.now_tile);

    let lz: Vec<u8> = vec![35];
    let original_hutype = cards.hutype;

    cards.assign(&hand, 0, cards.que, &cards.cpg.clone(), cards.hutype);

    cards.hutype = original_hutype;
    1
}

pub fn rm_ke_tiles(cards: &mut XlhzTiles, ts: &Vec<u8>) -> u64 {
    let ti = &mut cards.ti_hand;
    let lz: Vec<u8> = vec![35];  
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0);  

    let mut cpg: Vec<CPG> = Vec::new();
    let mut remaintiles = ts.clone();
    for c in &cards.cpg {
        if !remaintiles.contains(&c.tile) {
            cpg.push(*c);  
            continue;
        }
        remove_nv(&mut remaintiles, 1, c.tile);
    }

    let mut nt = cards.now_tile;
    for t in remaintiles {
        for _ in 0..3 {
            if hand_nt(&mut hand, &mut nt, t) == 0 {
                cards.assign(&hand, nt, cards.que, &cpg, cards.hutype);
                return 0;
            }
        }
    }

    cards.assign(&hand, nt, cards.que, &cpg, cards.hutype);
    1
}

pub fn rm_tong_ke_tiles(cards: &mut XlhzTiles, ketiles: Vec<u8>, tongkes: u64) -> u64 {
    let lz: Vec<u8> = vec![35]; // Assuming 35 represents a wildcard tile.
    let mut retv: Vec<u8> = Vec::new();
    let ret = MJRet { f: tongkes };
    ret.ret2v(&mut retv); // Assuming ret2v converts tongkes to a vector of tiles.

    let ti = &mut cards.ti_hand;
    let mut hand: Vec<u8> = Vec::new();
    ti.get_hands(&mut hand, 0); // Assuming this method gets all hand tiles.

    let mut cpg: Vec<CPG> = Vec::new();
    let mut remaintiles: Vec<u8>;

    for tk in 0..(retv.len() / 2) {
        remaintiles = Vec::new();
        for i in 0..2 {
            let tong = retv[tk * 2 + i];
            if !ketiles.contains(&tong) {
                remaintiles.push(tong);
            }
        }

        cpg.clear();
        for c in &cards.cpg {
            if !remaintiles.contains(&c.tile) {
                cpg.push(*c);
                continue;
            }
            remove_nv(&mut remaintiles, 1, c.tile);
        }

        let mut nt = cards.now_tile;
        let mut cptile = hand.clone();
        let mut isbreak = false;

        for ke in &remaintiles {
            for _ in 0..3 {
                if hand_nt(&mut cptile, &mut nt, *ke) == 0 {
                    isbreak = true;
                    break;
                }
            }
            if isbreak {
                break;
            }
        }

        if !isbreak {
            let ret = has_hu(&cptile, nt);
            if ret {
                for ke in &remaintiles {
                    for _ in 0..3 {
                        hand_nt(&mut hand, &mut nt, *ke);
                    }
                }
                cards.assign(&hand, nt, cards.que, &cpg, cards.hutype);
                return 1;
            }
        }
    }

    0
}

